<template>
  <view class="mxp-drop-down-single" :class="[cusClass]" :style="[cusStyle]">
    <!-- 顶部遮罩 -->
    <view v-if="data.show" :style="data.topMaskStyle" @click="onMaskClose" @touchmove.stop.passive="preventClick"></view>
    <!-- 标题部分 -->
    <view :id="id" class="drop-down-menu" :style="[{ background }, titleStyle]">
      <slot name="menu" :currentIndex="data.currentIndex">
        <title-item
          v-for="(item, index) in newTitleList"
          :key="index"
          :item="item"
          :index="index"
          :arrowsState="data.arrowsState"
          :titleItemWidth="newTitleItemWidth"
          :arrowsBackground="newArrowsBackground"
          :currentIndex="data.currentIndex"
          :activeColor="activeColor"
          :inactiveColor="inactiveColor"
          :menuFontSize="menuFontSize"
          :selected="newSelected.selectedDetails"
          @titleClick="titleItemClick"
        ></title-item>
      </slot>
    </view>
    <view
      v-if="data.showPopup"
      key="view-2"
      :style="[data.maskStyle, { transitionDuration: `${duration}ms`, opacity }]"
      class="mask"
      @click="onMaskClose"
      @touchmove.stop.passive="preventClick"
    >
      <view
        :style="[{ zIndex: zIndex! + 1, transform, transitionDuration: `${duration}ms`, opacity }]"
        class="popup"
        @click="preventClick"
        @touchmove.stop.passive="preventClick"
      >
        <view :style="{ background }" @click.stop.prevent="preventClick">
          <scroll-view :scrollY="true" :style="{ height: menuHeight }">
            <item-type1
              v-if="currTitleInfo.type === 1"
              :isAlone="currTitleInfo.isAlone"
              :itemFontSize="itemFontSize"
              :sideMenuBackground="sideMenuBackground"
              :menuHeight="menuHeight"
              :inactiveColor="inactiveColor"
              :activeColor="activeColor"
              :menuList="currMenuInfo.type2"
              :defaultValue="currSelected"
              @click="onItem2Click"
            ></item-type1>
            <item-type2
              v-else-if="currTitleInfo.type === 2"
              :isAlone="currTitleInfo.isAlone"
              :background="background"
              :sideMenuBackground="sideMenuBackground"
              :isMultiple="currTitleInfo.isMultiple"
              :uncheck="currTitleInfo.uncheck"
              :menuHeight="menuHeight"
              :inactiveColor="inactiveColor"
              :activeColor="activeColor"
              :itemFontSize="itemFontSize"
              :itemBackground="itemBackground"
              :menuList="currMenuInfo.type2"
              :defaultValue="currSelected"
              @click="onItem2Click"
            ></item-type2>
            <item-type3
              v-if="currTitleInfo.type === 3"
              :isAlone="currTitleInfo.isAlone"
              :sideMenuBackground="sideMenuBackground"
              :menuHeight="menuHeight"
              :inactiveColor="inactiveColor"
              :activeColor="activeColor"
              :itemFontSize="itemFontSize"
              :itemBackground="itemBackground"
              :itemActiveBackground="itemActiveBackground"
              :menuList="currMenuInfo.type2"
              :defaultValue="currSelected"
              @click="onItem2Click"
            ></item-type3>
            <item-type4
              v-if="currTitleInfo.type === 4"
              :isAlone="currTitleInfo.isAlone"
              :itemFontSize="itemFontSize"
              :menuHeight="menuHeight"
              :inactiveColor="inactiveColor"
              :activeColor="activeColor"
              :itemBackground="itemBackground"
              :menuList="currMenuInfo.type2"
              :defaultValue="currSelected"
              @click="onItem2Click"
            ></item-type4>
            <item-type5
              v-if="currTitleInfo.type === 5"
              :itemFontSize="itemFontSize"
              :menuList="currMenuInfo.type1"
              :menuHeight="menuHeight"
              :inactiveColor="inactiveColor"
              :activeColor="activeColor"
              :defaultValue="currSelected"
              @click="onItemClick"
            ></item-type5>
            <item-type6
              v-if="currTitleInfo.type === 6"
              :isMultiple="currTitleInfo.isMultiple"
              :uncheck="currTitleInfo.uncheck"
              :itemFontSize="itemFontSize"
              :menuHeight="menuHeight"
              :inactiveColor="inactiveColor"
              :activeColor="activeColor"
              :itemBackground="itemBackground"
              :background="background"
              :menuList="currMenuInfo.type1"
              :defaultValue="currSelected"
              @click="onItemClick"
            ></item-type6>
            <item-type7
              v-if="currTitleInfo.type === 7"
              :itemFontSize="itemFontSize"
              :menuHeight="menuHeight"
              :inactiveColor="inactiveColor"
              :activeColor="activeColor"
              :itemBackground="itemBackground"
              :itemActiveBackground="itemActiveBackground"
              :menuList="currMenuInfo.type1"
              :defaultValue="currSelected"
              @click="onItemClick"
            ></item-type7>
            <slot v-if="currTitleInfo.type === 9" name="child" :currMenuInfo="currMenuInfo" :currentIndex="data.currentIndex"></slot>
          </scroll-view>
          <view v-if="(currTitleInfo.type === 8 && !currTitleInfo.nowSubmit) || currTitleInfo.type !== 8" class="butt-view">
            <view class="btn-reset butt" :style="{ borderColor: buttonColor, color: buttonColor }" @click.stop="reset">重置</view>
            <view class="btn-complete butt" :style="{ backgroundColor: buttonColor, color: '#ffffff' }" @click.stop="submit">完成</view>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
  import { publicStyeProps } from '../mxp-tool/utils/public-props';
  import { getDomSize } from '../mxp-tool/utils/dom';
  import TitleItem from './components/title-item.vue';
  import ItemType1 from './components/item-type1.vue';
  import ItemType2 from './components/item-type2.vue';
  import ItemType3 from './components/item-type3.vue';
  import ItemType4 from './components/item-type4.vue';
  import ItemType5 from './components/item-type5.vue';
  import ItemType6 from './components/item-type6.vue';
  import ItemType7 from './components/item-type7.vue';
  import type {
    $NewSelected,
    $TrimDropDownMultipleListItem,
    $TrimDropDownMultipleListLevel1Item,
    $TrimDropDownMultipleListLevel2Item,
  } from './components/type';
  import type { $AllColorStr, $SizeUnitStr } from '@/mxp-ui/mxp-tool/types/interface';
  import { type CSSProperties, type PropType, computed, getCurrentInstance, nextTick, ref, shallowReactive } from 'vue';
  import { getOnlyID } from '../mxp-tool/utils/common';
  import { isObject } from '../mxp-tool/utils/verify';
  import { lightenDarkenColorStorage } from '../mxp-tool/utils/color';
  import { findItemsByKey, findItemsByKey2 } from '../mxp-tool/utils/arr';
  import mxpGetSysInfoStore from '../mxp-tool/store/mxp-store-sys-info';
  export type $TitleListItem = {
    [x: number | string]: unknown;
    /** 唯一的 key */
    key: number | string;
    /** 标题 */
    title: number | string;
    /** 显示的类型  1:侧边栏加普通列表布局，2:侧边栏加索引列表布局，3:侧边栏加横排按钮布局，4:纵向标题加横排按钮布局，5:普通列表布局，6:普通索引列表布局，7:横排按钮布局， 8:仅标题勾选 9:自定义内容 */
    type: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
    /** 是否为多选 */
    isMultiple?: boolean;
    /** 默认值 */
    defaultValue?: unknown;
    /** 单选时候是否立即提交( 此时清除和完成按钮不会显示) */
    nowSubmit?: boolean;
    /** 是否可以取消选中 (为 false 时 选中后再次点击 可以取消选中) */
    uncheck?: boolean;
    /**
     * 当 type 为 1,2,3,4 有效，具体作用如下：
     * 当为 true 时筛选中的值会是：{aloneKey1: ['选中值 1-1', '选中值 1-2'], aloneKey2: ['选中值 2-1','选中值 2-2']}
     * 当为 false 时筛选中的值会是：['选中值 1-1', '选中值 1-2', '选中值 2-1', '选中值 2-2']
     * 即会不会根据 aloneKey 分类，true 代表会分类，false 代表不会分类
     */
    isAlone?: boolean;
  };
  export type $TrimTitleListItem = Required<
    Pick<$TitleListItem, 'defaultValue' | 'isAlone' | 'isMultiple' | 'key' | 'nowSubmit' | 'title' | 'type' | 'uncheck'>
  > & { [x: number | string]: unknown; defaultValue: Record<number | string, unknown[]> | unknown[] };

  export type $MenuListItem = Record<number | string, unknown>;

  export type $DropDownMultipleResult = {
    /** 选中的值(键值对形式) */
    selected: Record<number | string, unknown>;
    /** 选中的详情(键值对形式) */
    selectedDetails: Record<number | string, unknown>;
  };

  export type $DropDownMultipleChange = $DropDownMultipleResult & {
    /** 当前改变的 title 数组的下标 */
    titleIndex: number;
    /** 当前改变的 menu 数组的下标 */
    menuIndex: number;
    /** 当前改变的 menu 数组 下面子选项的下标，仅当 type 为 1,2,3,4 有效 */
    menuChildIndex: number;
    /** 当前改变的 child 数组的 值 */
    value: unknown;
  };

  defineOptions({
    name: 'mxp-drop-down-multiple',
  });
  const props = defineProps({
    /**
     * 顶部菜单列表
     */
    titleList: { type: Array as PropType<$TitleListItem[]>, default: () => [] },
    /** 标题了的宽度，默认五个以内就平均分配，五个以上每项宽度为20% */
    titleItemWidth: { type: String as PropType<$SizeUnitStr | `${number}%`>, default: undefined },
    /** 筛选列表 */
    menuList: { type: Array as PropType<unknown[][]>, default: () => [] },
    /** 需要传给后端的key 必须保证唯一, 默认为: 'key' */
    aloneKey: { type: String, default: 'key' },
    /** 标题的显示字段的 key,不传取 childLabelKey 的值，如果都没有则为 'label' 即：props.titleLabelKey || props.childLabelKey || 'label' */
    titleLabelKey: { type: String, default: undefined },
    /** 选项列表的字段, 默认为: 'child' */
    childKey: { type: String, default: 'child' },
    /** 选中的值的字段的key, 默认为: 'value' */
    childValueKey: { type: String, default: 'value' },
    /** 显示字段的 key,不传取 titleLabelKey 的值，如果都没有则为'label' 即：props.childLabelKey || props.titleLabelKey || 'label' */
    childLabelKey: { type: String, default: undefined },
    /** 是否可以点击遮罩关闭 */
    maskClose: { type: Boolean, default: true },
    /** zIndex层级默认为 100 */
    zIndex: { type: Number, default: 100 },
    /** 筛选列表的高度 */
    menuHeight: { type: String as PropType<$SizeUnitStr>, default: `300px` },
    /** 筛选菜单的背景色 */
    background: { type: String as PropType<$AllColorStr>, default: '#ffffff' },
    /** 侧边栏的背景色 */
    sideMenuBackground: { type: String as PropType<$AllColorStr>, default: '#ffffff' },
    /** 未选中颜色 */
    inactiveColor: { type: String as PropType<$AllColorStr>, default: '#666' },
    /** 选中颜色颜色 */
    activeColor: { type: String as PropType<$AllColorStr>, default: '#0377fc' },
    /** 菜单的 的文字大小 */
    menuFontSize: { type: String as PropType<$SizeUnitStr>, default: `12px` },
    /** 筛选列表每一项的文字大小 */
    itemFontSize: { type: String as PropType<$SizeUnitStr>, default: `12px` },
    /** 筛选列表每一项的背景色（仅针对 type为 2，3,4,7 有效） */
    itemBackground: { type: String as PropType<$AllColorStr>, default: `#f2f2f2` },
    /** 动画持续时间 */
    duration: { type: Number, default: 300 },
    /** 按钮颜色 */
    buttonColor: { type: String as PropType<$AllColorStr>, default: '#0377fc' },
    /** 箭头的背景 */
    arrowsBackground: { type: String as PropType<$AllColorStr>, default: undefined },
    /** 标题的样式,可手动调整标题的高度边距等等 */
    titleStyle: { type: Object as PropType<CSSProperties>, default: () => ({}) },
    ...publicStyeProps,
  });
  defineSlots<{
    /** 自定义菜单 */
    menu?: () => void;
    /** 自定义筛选部分 */
    child?: (data: { currMenuInfo?: any; currentIndex: number }) => void;
  }>();
  const emits = defineEmits<{
    (e: 'submit', data: $DropDownMultipleResult): void;
    (e: 'change', data: $DropDownMultipleChange): void;
    (e: 'titleClick', data: { item: $TitleListItem; index: number }): void;
  }>();

  const instance = getCurrentInstance();

  const data = shallowReactive({
    isSubmit: true,
    menuStyle: {} as CSSProperties,
    topMaskStyle: { position: 'fixed', zIndex: props.zIndex } as CSSProperties,
    maskStyle: { position: 'fixed', zIndex: props.zIndex } as CSSProperties,
    popupHeight: '0px' as $SizeUnitStr,
    maskHeight: '0px' as $SizeUnitStr,
    currentIndex: 0,
    showPopup: false, // 动画结束后销毁
    show: false, // 显示或隐藏
    arrowsState: false,
  });

  const id = getOnlyID('mxp-drop-down-multiple');
  const opacity = ref(0);
  const transform = ref('translateY(-100%)');
  const animationTimeout = ref<NodeJS.Timeout | undefined>(undefined);
  /** 当前点击的标题 */
  const newTitleList = ref<$TrimTitleListItem[]>(updateTitleList(props.titleList));
  /** 菜单 */
  const newMenuList = ref<$TrimDropDownMultipleListItem[][]>(updateMenuList(props.menuList));

  /** 选中的 */
  const newSelected = ref<$NewSelected>(getActive());
  /** 存储初始化事的选中项 */
  const oldSelected = JSON.stringify(newSelected.value);
  /** 每个标题的宽度 */
  const newTitleItemWidth = computed<$SizeUnitStr | `${number}%`>(() => {
    return props.titleItemWidth ? props.titleItemWidth : newTitleList.value.length <= 5 ? `${100 / newTitleList.value.length}%` : '20%';
  });

  /** type 为 3 和 7 时 item 选中的背景 */
  const itemActiveBackground = computed<$AllColorStr>(() => lightenDarkenColorStorage(props.activeColor, 0.1) as $AllColorStr);
  /** 标题箭头的背景色 */
  const newArrowsBackground = computed<$AllColorStr>(
    () => props.arrowsBackground || (lightenDarkenColorStorage(props.background, 0.96, 'dark') as $AllColorStr)
  );

  /** 当前点击的标题 */
  const currTitleInfo = computed<$TrimTitleListItem>(() => newTitleList.value[data.currentIndex]!);
  /** 当前标题所对应的菜单 */
  const currMenuInfo = computed<{ type1: $TrimDropDownMultipleListLevel1Item[]; type2: $TrimDropDownMultipleListLevel2Item[] }>(() => {
    const obj: { type1: $TrimDropDownMultipleListLevel1Item[]; type2: $TrimDropDownMultipleListLevel2Item[] } = { type1: [], type2: [] };
    const list = newMenuList.value[data.currentIndex] || [];
    if ([1, 2, 3, 4].includes(currTitleInfo.value.type)) {
      obj.type2 = list as $TrimDropDownMultipleListLevel2Item[];
    } else {
      obj.type1 = list as $TrimDropDownMultipleListLevel1Item[];
    }
    return obj;
  });

  /** 当前选中的 */
  const currSelected = computed<Record<number | string, unknown[]> | unknown[] | undefined>(() => {
    const key = currTitleInfo.value.key || currTitleInfo.value.title;
    const value = newSelected.value.selected[key] ?? undefined;
    return value;
  });

  /**
   * 显示
   */
  async function show() {
    data.isSubmit = true;
    const rect = await getDomSize(`#${id}`, instance);
    const sys = mxpGetSysInfoStore().getSysInfo();
    data.menuStyle = {
      position: 'fixed',
      top: `${rect.top!}px`,
      left: `${rect.left!}px`,
      zIndex: props.zIndex + 1,
      width: `${rect.width}px`,
      height: `${rect.height!}px`,
    };
    data.topMaskStyle = {
      position: 'fixed',
      top: `${sys.value.windowTop}px`,
      left: 0,
      zIndex: props.zIndex,
      width: `${sys.value.windowWidth}px`,
      height: `${rect.top!}px`,
    };
    data.maskStyle = {
      position: 'fixed',
      bottom: `0px`,
      left: 0,
      zIndex: props.zIndex,
      width: `${sys.value.windowWidth}px`,
      height: `${sys.value.windowHeight - rect.top! - rect.height!}px`,
      backgroundColor: `rgba(0, 0, 0,0.3)`,
      overflow: 'hidden',
    };

    animationTimeout.value && clearTimeout(animationTimeout.value);
    opacity.value = 0;
    transform.value = `translateY(-100%)`;
    data.show = true;
    data.showPopup = true;

    nextTick(() => {
      setTimeout(() => {
        data.arrowsState = true;
        opacity.value = 1;
        transform.value = `translateY(0)`;
      }, 0);
    });
  }

  /**
   * 隐藏
   */
  function hide() {
    animationTimeout.value && clearTimeout(animationTimeout.value);
    opacity.value = 0;
    transform.value = `translateY(-100%)`;
    data.arrowsState = false;
    animationTimeout.value = setTimeout(() => {
      animationTimeout.value = undefined;
      data.show = false;
      data.showPopup = false;
    }, props.duration);
  }

  /**
   * 更新标题
   */
  function updateTitleList(list: $TitleListItem[]): $TrimTitleListItem[] {
    const oldList: $TitleListItem[] = JSON.parse(JSON.stringify(list));
    const newList = oldList.map((item) => {
      const newTitle: $TrimTitleListItem = {
        ...item,
        defaultValue: [],
        isMultiple: Boolean(item.isMultiple),
        uncheck: Boolean(item.uncheck ?? true),
        isAlone: Boolean(item.isAlone ?? true),
        nowSubmit: Boolean(item.nowSubmit ?? false),
      };
      if ([1, 2, 3, 4].includes(newTitle.type) && newTitle.isAlone) {
        if (isObject(item.defaultValue)) {
          const obj = item.defaultValue as Record<string, unknown[]>;
          Object.keys(obj).forEach((key) => {
            const def = obj[key] ?? '';
            const newDef = Array.isArray(def) ? def : def !== '' ? [def] : [];
            obj[key] = newDef;
          });
          newTitle.defaultValue = obj;
        } else {
          newTitle.defaultValue = {};
        }
      } else {
        const def = item.defaultValue ?? '';
        const newDef = Array.isArray(def) ? def : def !== '' ? [def] : [];
        newTitle.defaultValue = newDef;
      }
      return newTitle;
    });
    return newList;
  }

  /**
   * 更新数据
   */
  function updateMenuList(list: unknown[][]): $TrimDropDownMultipleListItem[][] {
    const oldList: unknown[][] = JSON.parse(JSON.stringify(list));
    const titleLabelKey = props.titleLabelKey || props.childLabelKey || 'label';
    const childLabelKey = props.childLabelKey || titleLabelKey || 'label';
    const newList: $TrimDropDownMultipleListItem[][] = [];
    newTitleList.value.forEach((titleItem: $TrimTitleListItem, titleIndex) => {
      const itemList = Array.isArray(oldList[titleIndex]) ? oldList[titleIndex]! : [];
      const newItemList: $TrimDropDownMultipleListItem[] = itemList.map((meunItem, meunIndex) => {
        if ([1, 2, 3, 4].includes(titleItem.type)) {
          const _meunItem = isObject(meunItem) ? meunItem : {};
          const childList: unknown[] = Array.isArray(_meunItem[props.childKey]) ? (_meunItem[props.childKey] as unknown[]) : [];
          const childArr: $TrimDropDownMultipleListLevel2Item['child'] = childList.map((child, childIndex) => {
            if (isObject(child)) {
              const value = child[props.childValueKey] || child[childLabelKey] || `value_${childIndex}`;
              return { label: String(child[childLabelKey] || `label_${childIndex}`), value, item: child };
            } else {
              return { label: String(child), value: child, item: child };
            }
          });
          const _newItemList: $TrimDropDownMultipleListLevel2Item = {
            key: (_meunItem[props.aloneKey] as number | string) || `aloneKey_${meunIndex}`,
            label: String(_meunItem[childLabelKey] || `label_${meunIndex}`),
            child: childArr,
          };
          return _newItemList;
        } else {
          if (isObject(meunItem)) {
            const value = meunItem[props.childValueKey] || meunItem[childLabelKey] || `value_${meunIndex}`;
            return {
              label: String(meunItem[childLabelKey] || `label_${meunIndex}`),
              value,
              item: meunItem,
            } as $TrimDropDownMultipleListLevel1Item;
          } else {
            return { label: String(meunItem), value: meunItem, item: meunItem } as $TrimDropDownMultipleListLevel1Item;
          }
        }
      });

      newList.push(newItemList);
    });

    return newList;
  }

  /**
   * 阻止传递
   */
  function preventClick() {
    // 阻止传递
  }

  /**
   * 点击遮罩
   */
  function onMaskClose() {
    props.maskClose && hide();
  }

  /**
   * 点击筛选列表里面的选项
   */
  function onItemClick(item: $TrimDropDownMultipleListLevel1Item, menuIndex: number) {
    const titleKey = currTitleInfo.value.key || currTitleInfo.value.title;
    const selected = newSelected.value.selected[titleKey]! as unknown[];
    const selectedDetails = newSelected.value.selectedDetails[titleKey]! as $TrimDropDownMultipleListLevel1Item[];
    setSelected(selected, selectedDetails, item, menuIndex, -1);
  }

  /**
   * 点击筛选列表里面的选项
   */
  function onItem2Click(item: $TrimDropDownMultipleListLevel1Item, key: number | string, menuIndex: number, menuChildIndex: number) {
    const titleKey = currTitleInfo.value.key || currTitleInfo.value.title;
    const isAlone = currTitleInfo.value.isAlone;

    let selected: unknown[] = [];
    let selectedDetails: $TrimDropDownMultipleListLevel1Item[] = [];
    if (isAlone) {
      const _value = newSelected.value.selected[titleKey]! as Record<number | string, unknown[]>;
      if (!_value[key]) {
        (newSelected.value.selected[titleKey] as Record<number | string, unknown[]>)[key] = [];
      }
      selected = _value[key]!;

      const _selectedDetails = newSelected.value.selectedDetails[titleKey]! as Record<number | string, $TrimDropDownMultipleListLevel1Item[]>;
      if (!_selectedDetails[key]) {
        (newSelected.value.selectedDetails[titleKey]! as Record<number | string, $TrimDropDownMultipleListLevel1Item[]>)[key] = [];
      }
      selectedDetails = _selectedDetails[key]!;
    } else {
      selected = newSelected.value.selected[titleKey]! as unknown[];
      selectedDetails = newSelected.value.selectedDetails[titleKey]! as $TrimDropDownMultipleListLevel1Item[];
    }

    setSelected(selected, selectedDetails, item, menuIndex, menuChildIndex);
  }

  /** 设置选中 */
  function setSelected(
    selected: unknown[],
    selectedDetails: $TrimDropDownMultipleListLevel1Item[],
    item: $TrimDropDownMultipleListLevel1Item,
    menuIndex: number,
    menuChildIndex: number
  ) {
    const isMultiple = currTitleInfo.value.isMultiple;
    const uncheck = currTitleInfo.value.uncheck;
    if (isMultiple) {
      const index1 = selected.indexOf(item.value);
      if (uncheck && index1 >= 0) {
        // 如果是必选且之前已经选中就取消选中
        selected.splice(index1, 1);
      } else if (index1 < 0) {
        selected.push(item.value);
      }

      const index2 = selectedDetails.findIndex((sel) => sel.value === item.value);
      if (uncheck && index2 >= 0) {
        // 如果是必选且之前已经选中就取消选中
        selectedDetails.splice(index2, 1);
      } else if (index2 < 0) {
        selectedDetails.push(item);
      }
    } else {
      if (uncheck || selected!.length <= 0) {
        // 如果是必选就直接设置
        selected[0] = item.value;
        selected.length = 1;
        selectedDetails[0] = item;
        selectedDetails.length = 1;
      } else {
        selected.splice(0, 1);
        selectedDetails.splice(0, 1);
      }
    }

    emits('change', { ...getResult(newSelected.value), titleIndex: data.currentIndex, menuIndex, menuChildIndex, value: item.item });
  }

  /**
   * 点击标题
   */
  function titleItemClick(item: $TrimTitleListItem, index: number) {
    emits('titleClick', { item: item as $TitleListItem, index });
    const isCheckbox = item.type === 8;
    if (data.currentIndex === index) {
      // 点击当前项
      data.showPopup || isCheckbox ? hide() : show();
    } else {
      (!data.showPopup && !isCheckbox) || (data.showPopup && !isCheckbox) ? show() : hide();
      data.currentIndex = index;
    }

    if (isCheckbox) {
      item.defaultValue = [!item.defaultValue[0]];
      const selected = getResult(newSelected.value);
      emits('change', { ...selected, titleIndex: data.currentIndex, menuIndex: -1, menuChildIndex: -1, value: item.defaultValue });

      emits('submit', selected);
    }
  }

  /** 得到选中的值 */
  function getActive(): $NewSelected {
    const selected: Record<number | string, Record<number | string, unknown[]> | unknown[]> = {};
    const selectedDetails: Record<number | string, $TrimDropDownMultipleListLevel1Item[] | Record<number | string, $TrimDropDownMultipleListLevel1Item[]>> = {};
    newTitleList.value.forEach((title, titleIndex) => {
      const key = title.key || title.title;
      selected[key] = title.defaultValue;
      if ([1, 2, 3, 4].includes(title.type)) {
        const meunList = (newMenuList.value[titleIndex] || []) as $TrimDropDownMultipleListLevel2Item[];
        if (title.isAlone) {
          const obj: Record<number | string, $TrimDropDownMultipleListLevel1Item[]> = {};
          meunList.forEach((meun) => {
            const value = (title.defaultValue as Record<number | string, unknown[]>)[meun.key] || [];
            obj[meun.key] = value.length > 0 ? findItemsByKey(value, meun.child, 'value').map((item) => item) : [];
          });
          selectedDetails[key] = obj;
        } else {
          let value = (title.defaultValue || []) as unknown[];
          let list: $TrimDropDownMultipleListLevel1Item[] = [];
          value.length > 0 &&
            meunList.forEach((meun) => {
              if (value.length > 0) {
                const { newList, newValue } = findItemsByKey2(value, meun.child, 'value');
                list = list.concat(newList.map((item) => item));
                value = newValue;
              }
            });
          selectedDetails[key] = list;
        }
      } else {
        const meunList = (newMenuList.value[titleIndex] || []) as $TrimDropDownMultipleListLevel1Item[];
        const value = (title.defaultValue || []) as unknown[];
        const list: $TrimDropDownMultipleListLevel1Item[] = value.length > 0 ? findItemsByKey(value, meunList, 'value').map((item) => item) : [];
        selectedDetails[key] = list;
      }
    });

    return { selected, selectedDetails };
  }

  /**
   * 得到结果
   */
  function getResult(active: $NewSelected): $DropDownMultipleResult {
    const _selected: $DropDownMultipleResult['selected'] = {};
    const _selectedDetails: $DropDownMultipleResult['selectedDetails'] = {};
    newTitleList.value.forEach((title) => {
      if (title.type === 8) {
        _selected[title.key] = Boolean(Array.isArray(active.selected[title.key]) ? active.selected[title.key]![0] : false);
        _selectedDetails[title.key] = _selected[title.key];
      } else if (Array.isArray(active.selected[title.key])) {
        const __select = active.selected[title.key]! as unknown[];
        const __selectDetails = active.selectedDetails[title.key] as $TrimDropDownMultipleListLevel1Item[];
        if (__select.length > 0) {
          _selected[title.key] = title.isMultiple ? __select : __select[0];
          _selectedDetails[title.key] = title.isMultiple ? __selectDetails.map((item) => item.item) : __selectDetails[0]!.item;
        }
      } else {
        const _selectObj = active.selected[title.key] as Record<number | string, unknown[]>;
        const __newSelect: Record<number | string, unknown> = {};
        const __newSelectDetails: Record<number | string, unknown> = {};
        for (const key in _selectObj) {
          const __select = _selectObj[key]!;
          if (__select.length > 0) {
            __newSelect[key] = title.isMultiple ? __select : __select[0];
            const __selectDetails = active.selectedDetails[title.key] as Record<number | string, $TrimDropDownMultipleListLevel1Item[]>;
            __newSelectDetails[key] = title.isMultiple ? (__selectDetails[key] || []).map((item) => item.item) : __selectDetails[key]![0]!.item;
          }
        }
        if (Object.keys(__newSelect).length > 0) {
          _selected[title.key] = __newSelect;
          _selectedDetails[title.key] = __newSelectDetails;
        }
      }
    });

    return { selected: _selected, selectedDetails: _selectedDetails };
  }

  /** 重置 */
  function reset() {
    newSelected.value = JSON.parse(oldSelected);
  }

  /** 提交 */
  function submit() {
    if (data.isSubmit) {
      data.isSubmit = false;
      const selected = getResult(newSelected.value);
      emits('submit', selected);
      hide();
    }
  }

  defineExpose({
    /** 显示 */
    show,
    /** 隐藏 */
    hide,
    /** 更新筛选数据 */
    updateMenuList,
    /** 更新标题数据 */
    updateTitleList,
    /** 得到选中的值 */
    getResult,
    /** 重置 */
    reset,
  });
</script>

<style scoped lang="scss">
  .mask {
    overflow: hidden;
    opacity: 0;
    transition-timing-function: ease-in-out;
    transition-duration: 0.3s;
    transition-property: opacity;

    .popup {
      transition-timing-function: ease-in-out;
      transition-duration: 0.3s;
      transition-property: transform, opacity;
      transform: translateY(-100%);
    }
  }

  .drop-down-menu {
    box-sizing: border-box;
    display: flex;
    flex: 1;
    flex-flow: row wrap;
    align-items: center;
    justify-content: flex-start;
    padding: 6px 0;
  }

  .butt-view {
    display: flex;
    flex: 1;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: 15px;

    .butt {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      width: 160px;
      height: 40px;
      border-radius: 40px;

      &.btn-reset {
        border-style: solid;
        border-width: 1px;
      }
    }
  }
</style>
